package nes

import (
	"fmt"
	"image"
	"image/png"
	"io/ioutil"
	"os"
	"rgones/nes/render"
)

func ShowTile(chrRom []byte, bank int, tileN int) *render.Frame {
	if bank > 1 {
		panic("bank must be less than or equal to 1")
	}

	frame := render.NewFrame()
	bank = bank * 0x1000

	tile := chrRom[bank+tileN*16 : bank+tileN*16+15]

	for y := 0; y <= 7; y++ {
		upper := tile[y]
		lower := tile[y+8]

		for x := 7; x >= 0; x-- {
			value := (1&upper)<<1 | (1 & lower)
			upper = upper >> 1
			lower = lower >> 1
			var rgb render.RGB
			switch value {
			case 0:
				rgb = render.SystemPalette[0x01]
			case 1:
				rgb = render.SystemPalette[0x23]
			case 2:
				rgb = render.SystemPalette[0x27]
			case 3:
				rgb = render.SystemPalette[0x30]
			default:
				panic("can't be")
			}
			frame.SetPixel(x, y, rgb.R, rgb.G, rgb.B)
		}
	}

	return frame
}

func ShowTileBank(chrRom []byte, bank int) *render.Frame {
	if bank > 1 {
		panic("bank must be less than or equal to 1")
	}

	frame := render.NewFrame()
	tileY := 0
	tileX := 0
	bank = bank * 0x1000

	for tileN := 0; tileN < 255; tileN++ {
		if tileN != 0 && tileN%20 == 0 {
			tileY += 10
			tileX = 0
		}
		tile := chrRom[bank+tileN*16 : bank+tileN*16+16]

		for y := 0; y <= 7; y++ {
			upper := tile[y]
			lower := tile[y+8]

			for x := 7; x >= 0; x-- {
				value := (1&upper)<<1 | (1 & lower)
				upper = upper >> 1
				lower = lower >> 1
				var rgb render.RGB
				switch value {
				case 0:
					rgb = render.SystemPalette[0x01]
				case 1:
					rgb = render.SystemPalette[0x23]
				case 2:
					rgb = render.SystemPalette[0x27]
				case 3:
					rgb = render.SystemPalette[0x30]
				default:
					panic("can't be")
				}
				frame.SetPixel(tileX+x, tileY+y, rgb.G, rgb.B, rgb.R)
			}
		}

		tileX += 10
	}

	return frame
}

func saveScreenState(frame []uint8, pngName string) {
	img := image.NewRGBA(image.Rect(0, 0, 256, 240))
	for i := 0; i < 256*240; i++ {
		img.Pix[i*4] = frame[i*3]
		img.Pix[i*4+1] = frame[i*3+1]
		img.Pix[i*4+2] = frame[i*3+2]
		img.Pix[i*4+3] = 0xff
	}
	pngRes := "../pngs/" + pngName + ".png"

	fmt.Println("saving to", pngRes)

	f, _ := os.Create(pngRes)
	defer f.Close()

	err := png.Encode(f, img)
	if err != nil {
		fmt.Println(err, "png encode error")
		return
	}
}

func TestShow() {

	// 读取文件
	romBytes, err := ioutil.ReadFile("../rom/wrecking.nes")
	if err != nil {
		panic(err)
	}

	rom, _ := NewRom(romBytes)
	right_bank := ShowTileBank(rom.ChrRom, 1)

	// 保存图片
	saveScreenState(right_bank.Data, "right_bank")
}
